package cn.ztuo.bitrade.util;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import okio.ByteString;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.TreeMap;


@Component
public class CoBoUtils {
    @Value("${cobo.host}")
    private String host;
    @Value("${cobo.apiKey}")
    private String apiKey;
    @Value("${cobo.apiSecret}")
    private String apiSecret;
    //测试环境
    //private  final String host = "https://api.sandbox.cobo.com";
    //正是环境
    //private  final String host ="https://api.custody.cobo.com";

    private  RestTemplate restTemplate = new RestTemplate();

    private  OkHttpClient HTTP_CLIENT = new OkHttpClient();

    private  String DEFAULT_PUBKEY = "pubkey(fetch by contact custody developer)";

    private  byte[] doubleSha256(String content) {
        return org.bitcoinj.core.Sha256Hash.hashTwice(content.getBytes());
    }

    private  byte[] hex2bytes(String s) {
        return okio.ByteString.decodeHex(s).toByteArray();
    }

    private  String bytes2Hex(byte[] b) {
        return okio.ByteString.of(b).hex();
    }

    private  String generateHmac256Signature(String content, String key) {
        okio.ByteString k = okio.ByteString.of(key.getBytes());
        return ByteString.of(content.getBytes()).hmacSha256(k).hex();
    }

    private  String generateEccSignature(String content, String key) {
        ECKey eckey = ECKey.fromPrivate(hex2bytes(key));
        return bytes2Hex(eckey.sign(Sha256Hash.wrap(doubleSha256(content))).encodeToDER());
    }

    private  String composeParams(TreeMap<String, Object> params) {
        StringBuffer sb = new StringBuffer();
        params.forEach((s, o) -> {
            try {
                sb.append(s).append("=").append(URLEncoder.encode(String.valueOf(o), "UTF-8")).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        });
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    private  boolean verifyResponse(String content, String sig, String pubkey) throws Exception {
        ECKey key = ECKey.fromPublicOnly(hex2bytes(pubkey));
        return key.verify(doubleSha256(content), hex2bytes(sig));
    }

    private  String request(String method, String path, TreeMap<String, Object> params) throws Exception {
        //String apiKey = "029e4a119a6ecd3fbea557862d5bab2eb76480e19e3ceedfaee942003b0fab5dd4";
        //String apiSecret = "619dd55a2e7f46127ee2e75a6d0e5b3f2a580b6fe0c1ac8b9514680f7f0e1602";
        method = method.toUpperCase();
        String nonce = String.valueOf(System.currentTimeMillis());

        String paramString = composeParams(params);

        String content = method + "|" + path + "|" + nonce + "|" + paramString;

        String signature = generateEccSignature(content, apiSecret);

        Request.Builder builder = new Request.Builder()
                .addHeader("Biz-Api-Key", apiKey)
                .addHeader("Biz-Api-Nonce", nonce)
                .addHeader("Biz-Api-Signature", signature);

        Request request;
        if ("GET".equalsIgnoreCase(method)) {
            request = builder
                    .url(host + path + "?" + paramString)
                    .build();
        } else if ("POST".equalsIgnoreCase(method)) {
            FormBody.Builder bodyBuilder = new FormBody.Builder();
            params.forEach((s, o) -> bodyBuilder.add(s, String.valueOf(o)));
            RequestBody formBody = bodyBuilder.build();
            request = builder
                    .url(host + path)
                    .post(formBody)
                    .build();
        } else {
            throw new RuntimeException("not supported http method");
        }
        try {
            Response response = HTTP_CLIENT.newCall(request).execute();
            String ts = response.header("BIZ_TIMESTAMP");
            String sig = response.header("BIZ_RESP_SIGNATURE");
            String body = response.body().string();
            int code = response.code();
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /*public  void main(String[] args) throws Exception {

       *//* TreeMap<String, Object> params = new TreeMap<>();
        //币种代号
        params.put("coin","BTC");
        //提现申请Id
        params.put("request_id",123);
        //提现地址
        params.put("address","1A96WDj6xU4dbTUj3QAc995fBVWZryKt8m");
        //提现数额, 注意要提前乘以相应币种的decimal, 例如提现1BTC， amount传100000000
        params.put("amount", 1000000000);
        //交易memo(在某些币种里面也叫tag), 当提现EOS, XRP, IOST等币时，根据情况传入
        params.put("memo","");

        JSONObject jsonObject = cashWithdrawal(params);


        //testGenerateKeysAndSignMessage();
    }*/
    /**
     * 获取对应币种的地址
     * @param params 币种代号
     * @return
     * @throws Exception
     */
    public  JSONObject newaddre(TreeMap<String, Object> params) throws Exception {
        String post = "POST";
        String path = "/v1/custody/new_address/";
        String res = request(post, path, params);
        return  JSONObject.parseObject(res);
    }

    /**
     *
     * 提币接口
     * @param map 请求的参数
     * @return
     */
    public  JSONObject cashWithdrawal(TreeMap<String, Object> map) throws Exception {
        String post = "POST";
        String path = "/v1/custody/new_withdraw_request/";
        String res = request(post, path, map);
        return  JSONObject.parseObject(res);
    }

    /**
     *
     * 获取提币信息
     * @param map 请求的参数
     * @return
     */
    public  JSONObject getWithdrawData(TreeMap<String, Object> map) throws Exception {
        String post = "GET";
        String path = "/v1/custody/withdraw_info_by_request_id/";
        String res = request(post, path, map);
        return  JSONObject.parseObject(res);
    }

    /**
     * 根据id去查询入账信息
     * @param map 封装参数信息
     * @return
     * @throws Exception
     */
    public  JSONObject transaction(TreeMap<String, Object> map) throws Exception {
        String post = "GET";
        String path = "/v1/custody/transaction/";
        String res = request(post, path, map);
        return  JSONObject.parseObject(res);
    }

    public  void testApi() throws Exception {
        TreeMap<String, Object> params = new TreeMap<>();
        params.put("coin", "BTC");
        String key = "02ba8c0c4c0a7c05b8f0c826994398595faf8eacb5f509ca3e656eb1be67243080";
        String secret = "19f03c10ba57b2e4c8e8e0777a5453d524d734a022284885b990c1fcf67f2602";
        String host = "https://api.sandbox.cobo.com";
        String res = request("GET", "/v1/custody/org_info/", params);
    }

    /**
     * 生成公匙私匙
     */
    public  void testGenerateKeysAndSignMessage() {
        ECKey key = new ECKey();
        String privHex = bytes2Hex(key.getPrivKeyBytes());
        String pubHex = bytes2Hex(key.getPubKey());
    }
}
